package game;


import globals.GlobalObjects;
import globals.GraphicalObjectType;
import globals.ObjectFactory;
import globals.ObjectType;
import graphics.FacingTex;
import graphics.GraphicalObject;
import graphics.Light;
import graphics.Skybox.SkyBox;

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.HashMap;

import physics.Avatar;
import physics.Carrot;
import physics.GameObject;
import physics.Planet;
import physics.Robot;
import physics.SatelliteBox;
import viewControllers.robot.RobotViewController;

import common.IParse;
import common.Point3D;
import common.Location.GOLocationsMap;
import common.Location.LocationsMap;


public class Parser {

	String filePath;
	int planetParamNum=6;

	public Parser(String filePath)
	{
		this.filePath = filePath;
	}

	public Game parse() 
	{
		Game game = new Game();
		HashMap<String, GameObject> objects = new HashMap<String, GameObject>();

		try {
			parseFile(objects, filePath);
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		Planet planet = null;
		Avatar avatar = null;
		GraphicalObject grObj = null;
		Planet planet4 = null;
		

		for (GameObject phObj:objects.values()){

			grObj = phObj.getGraphicalObject();
			if (grObj == null){
				if ( ( grObj = GlobalObjects.getGraphic(phObj.getPresentationName())) == null){
					grObj = new GraphicalObject();
				}
			}
			phObj.setGraphicalObject(grObj);
			grObj.setPhysicalObj(phObj);

			Universe.addGameObject( phObj);


			if (phObj.getName() != null && phObj.getName().equals("first")){
				planet = (Planet)phObj;
			}
			
			if (phObj.getName() != null && phObj.getName().equals("last")){
				planet4 = (Planet)phObj;
			}

			if (phObj instanceof Avatar){
				avatar = (Avatar)phObj;
			}
		}	

		
		Carrot giantCarrot = (Carrot)ObjectFactory.createGameObject(ObjectType.GIANTCARROT);
		giantCarrot.setCenter(new Point3D(0, 20,-100));
		giantCarrot.setPlanet(planet4);
		planet4.addObjectToPlanet(giantCarrot);
		planet4.pinpointToPlanet(giantCarrot);
		
		///////////////////////SstelliteCamera

		SatelliteBox cam = new SatelliteBox();
		cam.setPlanet(avatar.getPlanet());
		GraphicalObject gr = new GraphicalObject();
		cam.setGraphicalObject(gr);
		gr.setPhysicalObj(cam);
		Universe.addGameObject(cam);
		game.setSatCamera(cam);
		/////////////////////////////////////////

		game.setAvatar(avatar);
		TracingCamera tc = new TracingCamera();
		tc.setDistance(6);
		tc.setTarget(game.getAvatar().getPosition());
		Universe.setCamera(tc);
		return game;
	}

	private void parseFile(HashMap<String, GameObject> objects, String filename) throws FileNotFoundException,
	IOException, Exception {
		BufferedReader r =  new BufferedReader(new FileReader(filename));
		String line, curobj = null;
		IParse currentlyParsedObject = null;
		while ((line = r.readLine()) != null)
		{
			line = line.trim();
			if (line.length()==0 || (line.charAt(0) == '#')){  
				continue;
			}

			int ddIndex = line.indexOf(':'); //new object command
			int eqIndex = line.indexOf('='); //set parameter command
			int arIndex = line.indexOf('>'); //composite graphical objects command
			int pfIndex = line.indexOf('&'); //parse other file command


			if (ddIndex < 0 
					&& eqIndex < 0
					&& pfIndex < 0
					&& arIndex < 0) {
				throw new Exception();
			}

			else if (ddIndex >=0){
				if (currentlyParsedObject != null){
					currentlyParsedObject.commit();
					//System.out.println("[" + currentlyParsedObject.getName()+ "] loaded");
					currentlyParsedObject = null;
				}

				curobj = line.substring(0, ddIndex ).trim();
				String objName = line.substring( ddIndex+1, line.length() ).trim();

				currentlyParsedObject = createParsedObject( curobj,objects,objName);
				continue;
			}


			else if (eqIndex >= 0){
				String name = line.substring(0, eqIndex).trim();
				String[] args = line.substring(eqIndex + 1).trim().split("\\s+");
				currentlyParsedObject.setParameter(name, args);
				continue;
			}

			else if (arIndex >= 0){
				String attachName = line.substring(0, arIndex).trim();
				String attachToName = line.substring(arIndex + 1).trim();
				GlobalObjects.getGraphic(attachToName).addObject(
						GlobalObjects.getGraphic(attachName));
				continue;
			}
			else if (pfIndex >= 0){
				String fileName = line.substring(pfIndex + 1).trim();
				parseFile(objects, fileName);
				continue;
			}

			line = r.readLine();

		}
		if (currentlyParsedObject != null){

			currentlyParsedObject.commit();

		}
		r.close();
	}

	private IParse createParsedObject(String curobj,
			HashMap<String,GameObject> objects,
			String objName)
	throws IOException {

		GameObject gameObj = null;
		GraphicalObject grObj = null;
		boolean isGameObject = false; 
		boolean isGraphicObject = false;

		if(curobj.equals("planet")){
			gameObj = ObjectFactory.createGameObject(ObjectType.PLANET);
			isGameObject = true;

		}else if(curobj.equals("avatar")){
			gameObj = ObjectFactory.createGameObject(ObjectType.AVATAR);
			isGameObject = true;

		}else if(curobj.equals("bomb")){
			gameObj = ObjectFactory.createGameObject(ObjectType.BOMB);
			isGameObject = true;

		}else if(curobj.equals("food")){
			gameObj = ObjectFactory.createGameObject(ObjectType.CARROT);
			isGameObject = true;

		}else if(curobj.equals("portal")){
			gameObj = ObjectFactory.createGameObject(ObjectType.PORTAL);
			isGameObject = true;

		}else if(curobj.equals("lavaPlanet")){
			gameObj = ObjectFactory.createGameObject(ObjectType.LAVAPLANET);
			isGameObject = true;

		}else if(curobj.equals("sun")){
			gameObj = ObjectFactory.createGameObject(ObjectType.SUN);
			gameObj.setName(objName);
			//Universe.setSun(gameObj);
			isGameObject = true;

		}else if(curobj.equals("portalExit")){
			gameObj = ObjectFactory.createGameObject(ObjectType.EXIT);
			isGameObject = true;

		}else if(curobj.equals("sphere")){
			grObj = ObjectFactory.createGraphicalObject(GraphicalObjectType.SPHERE);
			isGraphicObject = true;

		}else if(curobj.equals("mesh")){
			grObj = ObjectFactory.createGraphicalObject(GraphicalObjectType.MESH);
			isGraphicObject = true;

		}else if(curobj.equals("box")){
			grObj = ObjectFactory.createGraphicalObject(GraphicalObjectType.BOX);
			isGraphicObject = true;

		}else if(curobj.equals("volcano")){
			grObj = ObjectFactory.createGraphicalObject(GraphicalObjectType.VOLCANO);
			isGraphicObject = true;

		}else if(curobj.equals("noLight")){
			grObj = ObjectFactory.createGraphicalObject(GraphicalObjectType.NOLIGHT);
			isGraphicObject = true;

		}else if(curobj.equals("lavaFire")){
			grObj = ObjectFactory.createGraphicalObject(GraphicalObjectType.LAVAFIRE);
			isGraphicObject = true;

		}else if(curobj.equals("explosion")){
			grObj = ObjectFactory.createGraphicalObject(GraphicalObjectType.EXPLOSION);
			isGraphicObject = true;

		}


		else if(curobj.equals("light")){
			Light light = new Light();
			grObj = light;
			grObj.setName(objName);
			isGraphicObject = true;

		}else if(curobj.equals("skybox")){
			SkyBox skybox = new SkyBox();
			skybox.setName(objName);
			Universe.getGrUniverse().setSkybox(skybox);
			grObj = skybox;
			isGraphicObject = true;

		}else if(curobj.equals("facingquad")){
			FacingTex facingTex = new FacingTex();
			facingTex.setName(objName);
			grObj = facingTex;
			isGraphicObject = true;

		}else if(curobj.equals("locationmap")){
			LocationsMap locmap = new LocationsMap();
			locmap.setName(objName);
			return locmap;

		}else if(curobj.equals("golocationmap")){
			GOLocationsMap golocmap = new GOLocationsMap();
			golocmap.setName(objName);
			return golocmap;
		}

		if (isGameObject){		
			gameObj.setName(objName);
			objects.put(objName, gameObj);
			GlobalObjects.putGameObject(gameObj.getName(), gameObj);
			return gameObj;
		}
		if (isGraphicObject){
			grObj.setName(objName);
			GlobalObjects.putGraphic(grObj.getName(), grObj);
			return grObj;
		}
		System.out.println("Erro : object type not defined");
		return gameObj;
	}


	public void reportError(String err)
	{
		System.out.println("ERROR: " + err);
	}




}
